package main

import (
	"fmt"
	"reflect"
)

// Golang 之 struct能不能比较

/*
	在golang的数据类型中
可比较：Integer，Floating-point，String，Boolean，Complex(复数型)，Pointer，Channel，Interface，Array
不可比较：Slice，Map，Function
 */

type A struct {
	Name string
	Age int
	Address *int
}
type B struct {
	name string
	sex bool
	hobby []string
}

type S struct {
	Name    string
	Age     int
	Address *int
	Data    []int
}

func test1()  {
	a1 := A{
		Name:    "jack",
		Age:     21,
		Address: new(int),
	}
	a2 := A{
		Name:    "jack",
		Age:     21,
		Address: new(int),
	}
	fmt.Println(a1 == a2)
}

func test2() {
	//b1 := B{
	//	name:  "lucy",
	//	sex:   false,
	//	hobby: []string{"哈哈哈", "嘿嘿"},
	//}
	//b2 := B{
	//	name:  "lucy",
	//	sex:   false,
	//	hobby: []string{"哈哈哈", "嘿嘿"},
	//}
	//fmt.Println(b1 == b2)   // nvalid operation: b1 == b2 (struct containing []string cannot be compared)
}

/*
借助 reflect.DeepEqual 函数 来对两个变量进行比较
 */
func test3() {
	a := S{
		Name:    "aa",
		Age:     1,
		Address: new(int),
		Data:    []int{1, 2, 3},
	}
	b := S{
		Name:    "aa",
		Age:     1,
		Address: new(int),
		Data:    []int{1, 2, 3},
	}
	fmt.Println(reflect.DeepEqual(a, b))
}

func main() {
	// 比较含有指针的结构体
	test1()  // false

	test3()  // true
}

// 总结
/*
	DeepEqual函数用来判断两个值是否深度一致。具体比较规则如下：
(1)不同类型的值永远不会深度相等
当两个数组的元素对应深度相等时，两个数组深度相等
当两个相同结构体的所有字段对应深度相等的时候，两个结构体深度相等
当两个函数都为nil时，两个函数深度相等，其他情况不相等（相同函数也不相等）
当两个interface的真实值深度相等时，两个interface深度相等
map的比较需要同时满足以下几个
	两个map都为nil或者都不为nil，并且长度要相等
	相同的map对象或者所有key要对应相同map对应的value也要深度相等

(2)指针，满足以下其一即是深度相等
	两个指针满足go的==操作符
	两个指针指向的值是深度相等的

(3)切片，需要同时满足以下几点才是深度相等
	两个切片都为nil或者都不为nil，并且长度要相等
	两个切片底层数据指向的第一个位置要相同或者底层的元素要深度相等
	注意：空的切片跟nil切片是不深度相等的

(4)其他类型的值（numbers, bools, strings, channels）如果满足go的==操作符，
则是深度相等的。要注意不是所有的值都深度相等于自己，例如函数，以及嵌套包含这些值的结构体，数组等

 */
